package com.portal.exception.service;

import com.portal.common.response.JsonBaseResult;
import com.portal.exception.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * 重试服务
 *
 * @author Amadeus
 * @date 2023/03/06
 */
@Slf4j
@Service
public class RetryService {

    /**
     * 重试
     *
     * @param code 代码
     * @return {@link JsonBaseResult}
     * @Retryable
     * value：抛出指定异常才会重试
     * include：和value一样，默认为空，当exclude也为空时，默认所有异常
     * exclude：指定不处理的异常
     * maxAttempts：最大重试次数，默认3次
     * backoff：重试等待策略，默认使用@Backoff，@Backoff的value默认为1000L，我们设置为2000L；multiplier（指定延迟倍数）默认为0，表示固定暂停1秒后进行重试，如果把multiplier设置为1.5，则第一次重试为2秒，第二次为3秒，第三次为4.5秒。
     */
    @Async
    @Retryable(value = Exception.class, maxAttempts = 3, backoff = @Backoff(delay = 3600, multiplier = 1.5))
    public JsonBaseResult retry(Integer code) {
        if (code > 0) {
            return JsonBaseResult.success();
        } else {
            log.info("retry开始");
            throw new AppException("异常重试");
        }
    }

    /**
     * 重试回调
     *
     * @param e e
     * @return {@link JsonBaseResult}
     * @Recover
     * 1. 方法的返回值必须与@Retryable方法一致
     * 2. 该回调方法与重试方法写在同一个实现类里面
     */
    @Recover
    public JsonBaseResult recover(AppException e) {
        log.info("回调方法执行！！！！");
        log.info(e.getMessage());
        //记日志到数据库 或者调用其余的方法
        return JsonBaseResult.fail();
    }
}
